package cn.chiship.framework.business.biz.business.service.impl;

import cn.chiship.framework.common.config.properties.GlobalProperties;
import cn.chiship.framework.common.pojo.vo.ExportDataResult;
import cn.chiship.framework.common.service.ExportService;
import cn.chiship.framework.docs.biz.service.FileResourcesService;
import cn.chiship.framework.docs.core.properties.FileUploadProperties;
import cn.chiship.sdk.cache.vo.CacheUserVO;
import cn.chiship.sdk.core.base.BaseResult;
import cn.chiship.sdk.core.base.ProgressResult;
import cn.chiship.sdk.core.base.constants.BaseConstants;
import cn.chiship.sdk.core.enums.ProgressResultEnum;
import cn.chiship.sdk.core.id.SnowflakeIdUtil;
import cn.chiship.sdk.core.util.*;
import cn.chiship.sdk.core.util.excel.ExcelHSSFUtil;
import cn.chiship.sdk.core.util.excel.ExcelXSSFUtil;
import cn.chiship.sdk.framework.base.BaseServiceImpl;
import cn.chiship.framework.business.biz.business.mapper.TestExampleMapper;
import cn.chiship.framework.business.biz.business.entity.TestExample;
import cn.chiship.framework.business.biz.business.entity.TestExampleExample;
import cn.chiship.framework.business.biz.business.service.TestExampleService;
import cn.chiship.sdk.framework.multipartFile.CloneInputStreams;
import cn.chiship.sdk.framework.multipartFile.InputStreamToMultipartFile;
import cn.chiship.sdk.framework.pojo.vo.UploadVo;
import cn.chiship.sdk.framework.util.ExportUtil;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 示例（正式环境可删除）业务接口实现层
 * 2022/9/15
 *
 * @author lijian
 */
@Service
public class TestExampleServiceImpl extends BaseServiceImpl<TestExample, TestExampleExample> implements TestExampleService {

    private static final Logger LOGGER = LoggerFactory.getLogger(TestExampleServiceImpl.class);

    @Resource
    TestExampleMapper testExampleMapper;

    @Resource
    ExportService exportService;

    @Resource
    FileUploadProperties fileUploadProperties;

    @Resource
    FileResourcesService fileResourcesService;

    @Resource
    GlobalProperties globalProperties;

    String fileName = "测试示例";
    String sheetName = "测试示例";
    String sheetTitle = "测试示例";

    @Override
    public BaseResult insertSelective(TestExample testExample) {
        testExample.setFullPinyin(ChineseCharToEn.getAllFirstLetters(testExample.getName()).toUpperCase());
        testExample.setFirstLetter(ChineseCharToEn.getFirstLetter(testExample.getName()).toUpperCase());
        return super.insertSelective(testExample);
    }

    @Override
    public void asyncExportData(HttpServletResponse response, String taskId, Map<String, Object> paramMap) {
        try {
            processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_SEARCH_DATABASE_ENUM));
            Thread.sleep(1000);
            ExportDataResult exportDataResult = assemblyExportData(paramMap);
            processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_DOING_ENUM, "查询出" + exportDataResult.getTotal() + "条符合条件记录..."));
            Thread.sleep(1000);
            processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_FILE_ASSEMBLY_ENUM));

            //此行代码一定要放到最后执行，否则前段永远得不到下载流
            String exportType = paramMap.get("exportType").toString();
            byte[] bytes = ExportUtil.getInstance().getExportBytesByType(
                    exportType,
                    fileName,
                    fileName,
                    exportDataResult.getLabels(),
                    exportDataResult.getValues());
            processStatusHm.put(taskId, ProgressResult.out(exportType, fileName, bytes));

        } catch (Exception e) {
            e.printStackTrace();
            processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_ERROR_ENUM, e.getLocalizedMessage()));
        }

    }

    @Override
    public void exportData(HttpServletResponse response, Map<String, Object> paramMap) throws Exception {
        ExportDataResult exportDataResult = assemblyExportData(paramMap);
        exportService.exportByType(
                response,
                paramMap.get("exportType").toString(),
                fileName,
                sheetName,
                sheetTitle,
                exportDataResult.getLabels(),
                exportDataResult.getValues());
    }


    @Override
    @Async
    public void asyncImportData(InputStream inputStream, String taskId, Map<String, Object> paramMap) {
        try {
            processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_DOING_ENUM));

            System.out.println("条件：" + JSON.toJSONString(paramMap));
            String fileExt = StringUtil.getString(paramMap.get("ext"));
            if (StringUtil.isNullOrEmpty(fileExt)) {
                fileExt = BaseConstants.EXPORT_FORMAT_XLS;
            }

            String fileSave = StringUtil.getString(paramMap.get("fileSave"));
            if (StringUtil.isNullOrEmpty(fileSave)) {
                fileSave = "0";
            }
            Thread.sleep(1000);
            if ("1".equals(fileSave)) {
                String catalogId = globalProperties.getImportDataCatalog();
                processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_DOING_ENUM, "您开启了保留源文件，正在保存源文件..."));
                Thread.sleep(1000);
                if (StringUtil.isNullOrEmpty(fileUploadProperties.getFilePathByCatalogId(catalogId))) {
                    processStatusHm.put(
                            taskId,
                            ProgressResult.out(ProgressResultEnum.PROGRESS_ERROR_ENUM, "您还未配置【chiship.importData.catalogId】属性或catalogId不存在"));
                }
                processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_DOING_ENUM, "源文件保存中..."));
                CacheUserVO cacheUserVO = (CacheUserVO) paramMap.get("userVo");
                try {
                    String fileName = StringUtil.getString(paramMap.get("fileName"));
                    if (StringUtil.isNullOrEmpty(fileName)) {
                        fileName = DateUtils.dateTimeNow() + "_" + SnowflakeIdUtil.generateStrId() + '.' + fileExt;
                    } else {
                        fileName = DateUtils.dateTimeNow() + "_" + fileName;
                    }

                    String contentType = StringUtil.getString(paramMap.get("contentType"));
                    if (StringUtil.isNullOrEmpty(fileName)) {
                        contentType = "application/vnd.ms-excel";
                    }

                    /**
                     * 以下两行代码，是必须写的，同一个文件流要深克隆
                     */
                    CloneInputStreams cloneInputStreams = CloneInputStreams.getCloneInputStream(inputStream);
                    inputStream = cloneInputStreams.getInputStream1();
                    MultipartFile multipartFile = InputStreamToMultipartFile.inputStreamConvert(fileName, contentType, cloneInputStreams.getInputStream2());
                    BaseResult baseResult = fileResourcesService.uploadFile(multipartFile, catalogId, cacheUserVO);
                    if (baseResult.isSuccess()) {
                        UploadVo uploadVo = (UploadVo) baseResult.getData();
                        processStatusHm.put(
                                taskId,
                                ProgressResult.out(ProgressResultEnum.PROGRESS_DOING_ENUM,
                                        String.format("源文件保存成功,明细如下【文件名：%s，唯一标识：%s】", uploadVo.getOriginalName(), uploadVo.getUuid())));
                        Thread.sleep(1000);
                        processStatusHm.put(
                                taskId,
                                ProgressResult.out(ProgressResultEnum.PROGRESS_DOWN_ENUM, String.format(uploadVo.getUuid())));
                        Thread.sleep(1000);
                    } else {
                        processStatusHm.put(
                                taskId,
                                ProgressResult.out(ProgressResultEnum.PROGRESS_ERROR_ENUM, baseResult.getData().toString()));
                        return;
                    }
                } catch (Exception e) {
                    e.getLocalizedMessage();
                    processStatusHm.put(
                            taskId,
                            ProgressResult.out(ProgressResultEnum.PROGRESS_ERROR_ENUM, e.getLocalizedMessage()));
                    return;
                }
            } else {
                processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_DOING_ENUM, "您开启了不保留源文件..."));
            }
            processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_DOING_ENUM));

            //
            Map<String, String> headerTitleMap = new LinkedHashMap<>();
            headerTitleMap.put("code", "序号");
            headerTitleMap.put("name", "名称");
            headerTitleMap.put("adCode", "区域代码");
            BaseResult baseResult = null;
            if (BaseConstants.EXPORT_FORMAT_XLS.equals(fileExt)) {
                ExcelHSSFUtil.load(inputStream);
                baseResult = ExcelHSSFUtil.readExcel(1, 2, 3, headerTitleMap);
            }
            if (BaseConstants.EXPORT_FORMAT_XLSX.equals(fileExt)) {
                ExcelXSSFUtil.load(inputStream);
                baseResult = ExcelXSSFUtil.readExcel(1, 2, 3, headerTitleMap);
            }
            if (BaseConstants.EXPORT_FORMAT_CSV.equals(fileExt)) {
                processStatusHm.put(
                        taskId,
                        ProgressResult.out(ProgressResultEnum.PROGRESS_ERROR_ENUM, "暂不支持CSV数据导入"));
                return;
            }


            if (!baseResult.isSuccess()) {
                processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_ERROR_ENUM, baseResult.getData().toString()));
                return;
            }
            ArrayList<Map<String, String>> dataResult = (ArrayList) baseResult.getData();

            processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_DOING_ENUM, "解析出" + dataResult.size() + "条数据！"));
            Thread.sleep(1000);
            processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_DOING_ENUM, "数据正在比对入库中..."));
            int finishCount = 0;
            for (Map<String, String> map : dataResult) {
                String name = map.get("name");
                String adCode = map.get("adCode");
                TestExample testExample = new TestExample();
                testExample.setName(name);
                testExample.setAdCode(adCode);
                insertSelective(testExample);
                processStatusHm.put(
                        taskId,
                        ProgressResult.out(ProgressResultEnum.PROGRESS_PROGRESS_ENUM, "解析出" + dataResult.size() + "条数据！已完成：" + (StringUtil.formatPercent(finishCount++, dataResult.size())) + "%！")
                );
                Thread.sleep(500);
            }
            processStatusHm.put(
                    taskId,
                    ProgressResult.out(ProgressResultEnum.PROGRESS_PROGRESS_ENUM, "已完成：100%！")
            );
            /**
             * 此行代码解决 进度不满100%时先睡眠1秒 强制更到100%
             */
            Thread.sleep(1000);
            processStatusHm.put(
                    taskId,
                    ProgressResult.out(ProgressResultEnum.PROGRESS_FINISH_ENUM, "入库完成！")
            );
        } catch (Exception e) {
            e.printStackTrace();
            processStatusHm.put(
                    taskId,
                    ProgressResult.out(ProgressResultEnum.PROGRESS_ERROR_ENUM, e.getLocalizedMessage())
            );
        }
    }


    /**
     * 组装导出数据，此方法纯属为了同时支持同步导出与异步导出，减少代码书写
     *
     * @return
     */
    public ExportDataResult assemblyExportData(Map<String, Object> paramMap) {
        List<String> labels = new ArrayList<>();
        List<List<String>> valueList = new ArrayList<>();
        int total = 0;


        //是否模板
        Boolean template = false;
        if (paramMap.containsKey("template")) {
            template = Boolean.valueOf(StringUtil.getString(paramMap.get("template")));
        }
        if (template) {
            labels.add("名称");
            labels.add("区域代码");

            List<String> values = new ArrayList<>();
            values.add("示例名称");
            values.add("示例代码");
            valueList.add(values);
        } else {
            labels.add("编号");
            labels.add("名称");
            labels.add("全拼");
            labels.add("首字母");
            labels.add("区域代码");
            labels.add("新增时间");
            labels.add("最后修改时间");

            TestExampleExample testExampleExample = new TestExampleExample();
            List<TestExample> testExamples = testExampleMapper.selectByExample(testExampleExample);

            for (TestExample testExample : testExamples) {
                List<String> values = new ArrayList<>();
                values.add(testExample.getId());
                values.add(testExample.getName());
                values.add(testExample.getFullPinyin());
                values.add(testExample.getFirstLetter());
                values.add(testExample.getAdCode());
                values.add(DateUtils.dateTime(testExample.getGmtCreated()));
                values.add(DateUtils.dateTime(testExample.getGmtModified()));
                valueList.add(values);
            }

            total = testExamples.size();
        }

        ExportDataResult exportDataResult = new ExportDataResult(
                labels,
                valueList,
                total
        );
        return exportDataResult;
    }


}
